package com.valsong.sandbox.mock.context;

import com.alibaba.jvm.sandbox.api.listener.ext.EventWatchBuilder;
import com.alibaba.jvm.sandbox.api.listener.ext.EventWatcher;
import com.alibaba.jvm.sandbox.api.resource.ModuleEventWatcher;
import com.valsong.sandbox.mock.AdviceListenerProvider;
import com.valsong.sandbox.mock.EventWatcherProvider;
import com.valsong.sandbox.mock.MockConfig;

import javax.inject.Inject;
import java.util.Optional;


/**
 * InternalEventWatcherProvider
 *
 * @author Val Song
 */
public class InternalEventWatcherProvider implements EventWatcherProvider {

    @Inject
    private AdviceListenerProvider adviceListenerProvider;

    @Override
    public EventWatcher newEventWatcher(ModuleEventWatcher moduleEventWatcher, MockConfig mockConfig) {

        String[] parameterTypes = mockConfig.getParameterTypes();

        //是否包含子类
        boolean includeSubClasses = Optional.ofNullable(mockConfig)
                .map(MockConfig::getIncludeSubClasses)
                .orElse(false);

        //是否包含被Bootstrap加载的类
        boolean includeBootstrap = Optional.ofNullable(mockConfig)
                .map(MockConfig::getIncludeBootstrap)
                .orElse(false);

        //类是否拥有某一组标注
        String[] hasAnnotationTypes = mockConfig.getHasAnnotationTypes();

        //类是否声明实现了某一组接口
        String[] hasInterfaceTypes = mockConfig.getHasInterfaceTypes();

        EventWatchBuilder.IBuildingForClass iBuildingForClass = new EventWatchBuilder(moduleEventWatcher)
                .onClass(mockConfig.getClassPattern())
                .isIncludeSubClasses(includeSubClasses)
                .isIncludeBootstrap(includeBootstrap);

        if (hasAnnotationTypes != null && hasAnnotationTypes.length > 0) {
            iBuildingForClass = iBuildingForClass.hasAnnotationTypes(hasAnnotationTypes);
        }

        if (hasInterfaceTypes != null && hasInterfaceTypes.length > 0) {
            iBuildingForClass = iBuildingForClass.hasInterfaceTypes(hasInterfaceTypes);
        }

        EventWatchBuilder.IBuildingForBehavior iBuildingForBehavior = iBuildingForClass.onBehavior(mockConfig.getMethodPattern());

        //参数类型
        if (parameterTypes != null && parameterTypes.length > 0) {
            iBuildingForBehavior = iBuildingForBehavior.withParameterTypes(parameterTypes);
        }

        return iBuildingForBehavior
                //.onWatching()
                //.withCall()
                .onWatch(adviceListenerProvider.newAdviceListener(mockConfig));
    }
}
